﻿using Castle.DynamicProxy;
using JX.Infrastructure.NLog;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace JX.Infrastructure.Common
{
	/// <summary>
	/// autofac通用拦截器，在需要拦截的接口上添加[Intercept(typeof(CommonAOP))]属性
	/// </summary>
	public class CommonAOP : IInterceptor
	{
		private readonly IHttpContextAccessor _accessor;

		/// <summary>
		/// 构造器
		/// </summary>
		public CommonAOP(IHttpContextAccessor accessor)
		{
			_accessor = accessor;
		}

		/// <summary>
		/// 实例化IInterceptor唯一方法
		/// </summary>
		/// <param name="invocation">包含被拦截方法的信息</param>
		public void Intercept(IInvocation invocation)
		{
			var mb = invocation.Method as MethodBase;
			string fullName = mb.DeclaringType.FullName + "." + invocation.Method.Name;
			string dataIntercept = "" +
				$"【当前操作用户】：{ _accessor.HttpContext.User.Identity.Name} \r\n" +
				$"【当前执行方法】：{fullName} \r\n" +
				$"【携带的参数有】： {string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())} \r\n";

			try
			{
				//在被拦截的方法执行完毕后 继续执行当前方法，注意是被拦截的是异步的
				invocation.Proceed();
				
				var type = invocation.Method.ReturnType;
				if (typeof(Task).IsAssignableFrom(type))
				{
					var resultProperty = type.GetProperty("Result");
					dataIntercept += ($"【执行完成结果】：{JsonConvert.SerializeObject(resultProperty.GetValue(invocation.ReturnValue))}");
				}
				else
				{
					dataIntercept += ($"【执行完成结果】：{invocation.ReturnValue}");
				}
				NLogHelper.Info(dataIntercept);
			}
			catch (Exception ex)
			{
				NLogHelper.Error(dataIntercept, ex);
			}

		}

		/// <summary>
		/// 是否异步执行的方法
		/// </summary>
		/// <param name="method"></param>
		/// <returns></returns>
		public static bool IsAsyncMethod(MethodInfo method)
		{
			return (
				method.ReturnType == typeof(Task) ||
				(method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
				);
		}

	}
}
